package jia.core.calculations;

import jia.game.GenericFlags;
import jia.core.characters.GameCharacter;
import jia.core.state.CombatState;
import org.apache.log4j.Logger;

import java.util.ArrayList;

public class Combat {
    private static final Logger log = Logger.getLogger(Combat.class);

    /**
     * Checks to see if the opponent is dead
     *
     * @param characterState
     * @return
     */
    public static boolean isOpponentDead(CombatState characterState, ArrayList combatants) {
        boolean retVal = false;
        try {
            GameCharacter thisCharacter = getOpposingCharacter(characterState, combatants);
            if (thisCharacter == null) {
                retVal = true;
            } else {
                retVal = thisCharacter.getIsDead();
            }
        } catch (Exception e) {
            if (GenericFlags.errorMessages) {
                log.error(e.getMessage());
            }
        }
        return retVal;
    }

    /**
     * Returns the opposing characterState object for a given characterState.  Basically, returns
     * who this characterState is attacking for this round
     *
     * @param characterState
     * @return
     */
    public static GameCharacter getOpposingCharacter(CombatState characterState, ArrayList combatants) {

        GameCharacter opponent = null;
        CombatState combatant;
        try {
            for (Object combatant1 : combatants) {
                combatant = (CombatState) combatant1;
                if (characterState.getOpponentId() == combatant.getCharacter().getId()) {
                    opponent = combatant.getCharacter();
                }
            }
        } catch (Exception e) {
            if (GenericFlags.errorMessages) {
                log.error("An error occured while retrieving this characters opponent!" + e.getMessage());
            }
        }
        return opponent;
    }

    /**
     * Returns the opposing characterState object for a given characterState.  Basically, returns
     * who this characterState is attacking for this round
     *
     * @param characterState
     * @return
     */
    public static CombatState getOpposingCharacterState(CombatState characterState, ArrayList combatants) {

        CombatState opponent = null;
        CombatState combatant;
        try {
            for (Object combatant1 : combatants) {
                combatant = (CombatState) combatant1;
                if (characterState.getOpponentId() == combatant.getCharacter().getId()) {
                    opponent = combatant;
                }
            }
        } catch (Exception e) {
            if (GenericFlags.errorMessages) {
                log.error("An error occured while retrieving this characters opponent!" + e.getMessage());
            }
        }
        return opponent;
    }

    /**
     * Returns true if all the heroes are dead
     *
     * @return
     */
    public static boolean heroesAllDead(ArrayList combatants) {
        boolean isTrue = false;
        int deadCount = 0;
        int heroCount = 0;
        //loop through the list and check if all the heroes are dead
        try {
            CombatState characterState;
            for (Object combatant : combatants) {
                characterState = (CombatState) combatant;
                if (!characterState.isEnemy()) {
                    heroCount = heroCount + 1;
                    if (characterState.getCharacter().getIsDead()) {
                        deadCount = deadCount + 1;
                    }
                }
            }
            if (deadCount == heroCount) {
                if (GenericFlags.debugMessages) {
                    log.debug("All the heroes are dead!");
                }
                isTrue = true;
            }
            if (GenericFlags.debugMessages) {
                log.debug("There are " + heroCount + " heroes, " + deadCount + " are dead");
            }
        } catch (Exception e) {
            if (GenericFlags.errorMessages) {
                log.error("An error occured while determining if the heroes were all dead!" + e.getMessage());
            }
        }
        return isTrue;

    }

    /**
     * Returns true if all the enemies are dead
     *
     * @return
     */
    public static boolean enemiesAllDead(ArrayList combatants) {
        boolean isTrue = false;
        int deadCount = 0;
        int enemyCount = 0;
        try {
            CombatState characterState;
            //loop through the list and check if all the heroes are dead
            for (Object combatant : combatants) {
                characterState = (CombatState) combatant;
                if (characterState.isEnemy()) {
                    enemyCount = enemyCount + 1;
                    if (characterState.getCharacter().getIsDead()) {
                        deadCount = deadCount + 1;
                    }
                }
            }
            if (deadCount == enemyCount) {
                if (GenericFlags.debugMessages) {
                    log.debug("All the enemies are dead!");
                }
                isTrue = true;
            }
            if (GenericFlags.debugMessages) {
                log.debug("There are " + enemyCount + " enemies, " + deadCount + " are dead");
            }
        } catch (Exception e) {
            if (GenericFlags.errorMessages) {
                log.error("An error occured while determining if the enemies were all dead!" + e.getMessage());
            }
        }
        return isTrue;
    }

    /**
     * Returns a boolean that tells if all the members of either team have been killed.
     *
     * @return
     */
    public static boolean isEitherFactionDefeated(ArrayList combatants) {
        try {
            if (GenericFlags.debugMessages) {
                log.debug("Checking to see if either group has been defeated");
            }
            boolean heroes = heroesAllDead(combatants);
            boolean enemies = enemiesAllDead(combatants);
            if (heroes || enemies) {
                return true;
            }
        } catch (Exception e) {
            if (GenericFlags.errorMessages) {
                log.error(e.getMessage());
            }
        }
        return false;
    }

    /**
     * Not sure if this is needed yet or not, but its a utility method that will extract
     * the heroes from the main combat list into their own list
     *
     * @return
     */
    public static ArrayList<CombatState> extractEnemiesAsList(ArrayList combatants) {
        ArrayList<CombatState> enemyArray = new ArrayList<CombatState>();
        try {
            CombatState characterState;
            //loop through the list and check if all the heroes are dead
            for (Object combatant : combatants) {
                characterState = (CombatState) combatant;
                if (characterState.isEnemy()) {
                    if (!characterState.getCharacter().getIsDead()) {
                        enemyArray.add(characterState);
                    }
                }
            }
        } catch (Exception e) {
            if (GenericFlags.errorMessages) {
                log.error("An error occured while extracting the heroes into their own list!" + e.getMessage());
            }
        }
        return enemyArray;
    }

    /**
     * Not sure if this is needed yet or not, but its a utility method that will extract
     * the heroes from the main combat list into their own list
     *
     * @return
     */
    public static ArrayList<CombatState> extractHeroesAsList(ArrayList combatants) {
        ArrayList<CombatState> heroArray = new ArrayList<CombatState>();
        try {
            CombatState characterState;
            //loop through the list and check if all the heroes are dead
            for (Object combatant : combatants) {
                characterState = (CombatState) combatant;
                if (!characterState.isEnemy()) {
                    if (!characterState.getCharacter().getIsDead()) {
                        heroArray.add(characterState);
                    }
                }
            }
        } catch (Exception e) {
            if (GenericFlags.errorMessages) {
                log.error("An error occured while extracting the heroes into their own list!" + e.getMessage());
            }
        }
        return heroArray;
    }
}
